home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / abbrev.c next >
Encoding:
C/C++ Source or Header  |  1995-08-04  |  8.5 KB  |  266 lines

  1. /* Primitives for word-abbrev mode.
  2.    Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of XEmacs.
  5.  
  6. XEmacs is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by the
  8. Free Software Foundation; either version 2, or (at your option) any
  9. later version.
  10.  
  11. XEmacs is distributed in the hope that it will be useful, but WITHOUT
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with XEmacs; see the file COPYING.  If not, write to the Free
  18. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Synched up with: FSF 19.28.  Note that there are many more functions in
  21.    FSF's abbrev.c.  These have been moved into Lisp in XEmacs. */
  22.  
  23. /* This file has been Mule-ized. */
  24.  
  25. #include <config.h>
  26. #include "lisp.h"
  27.  
  28. #include "commands.h"
  29. #include "buffer.h"
  30. #include "window.h"
  31. #include "insdel.h"
  32.  
  33. /* An abbrev table is an obarray.
  34.    Each defined abbrev is represented by a symbol in that obarray
  35.    whose print name is the abbreviation.
  36.    The symbol's value is a string which is the expansion.
  37.    If its function definition is non-nil, it is called
  38.    after the expansion is done.
  39.    The plist slot of the abbrev symbol is its usage count. */
  40.  
  41. /* The table of global abbrevs.  These are in effect
  42.    in any buffer in which abbrev mode is turned on. */
  43. Lisp_Object Vglobal_abbrev_table;
  44.  
  45. int abbrev_all_caps;
  46.  
  47. /* Non-nil => use this location as the start of abbrev to expand
  48.  (rather than taking the word before point as the abbrev) */
  49. Lisp_Object Vabbrev_start_location;
  50.  
  51. /* Buffer that Vabbrev_start_location applies to */
  52. Lisp_Object Vabbrev_start_location_buffer;
  53.  
  54. /* The symbol representing the abbrev most recently expanded */
  55. Lisp_Object Vlast_abbrev;
  56.  
  57. /* A string for the actual text of the abbrev most recently expanded.
  58.    This has more info than Vlast_abbrev since case is significant.  */
  59. Lisp_Object Vlast_abbrev_text;
  60.  
  61. /* Character address of start of last abbrev expanded */
  62. int last_abbrev_point;
  63.  
  64. /* Hook to run before expanding any abbrev.  */
  65. Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
  66.  
  67.  
  68. /* Expand the word before point, if it is an abbrev.
  69.    Returns Qt if an expansion is done. */
  70.  
  71. DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
  72.   "Expand the abbrev before point, if there is an abbrev there.\n\
  73. Effective when explicitly called even when `abbrev-mode' is nil.\n\
  74. Returns t if expansion took place.")
  75.   ()
  76. {
  77.   /* This function can GC */
  78.   REGISTER Bufbyte *buffer, *p;
  79.   REGISTER Bufpos wordstart, wordend, idx;
  80.   Charcount whitecnt;
  81.   Charcount uccount = 0, lccount = 0;
  82.   REGISTER Lisp_Object sym;
  83.   Lisp_Object expansion, hook, value;
  84.   struct buffer *buf = current_buffer;
  85.   Lisp_Object lbuf;
  86.   int oldmodiff = BUF_MODIFF (buf);
  87.  
  88.   XSETBUFFER (lbuf, buf);
  89.   if (!NILP (Vrun_hooks))
  90.     call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
  91.   /* If the hook changes the buffer, treat that as having "done an
  92.      expansion".  */
  93.   value = (BUF_MODIFF (buf) != oldmodiff ? Qt : Qnil);
  94.  
  95.   if (!BUFFERP (Vabbrev_start_location_buffer) ||
  96.       XBUFFER (Vabbrev_start_location_buffer) != buf)
  97.     Vabbrev_start_location = Qnil;
  98.   if (!NILP (Vabbrev_start_location))
  99.     {
  100.       wordstart = get_bufpos (buf, Vabbrev_start_location, GB_COERCE_RANGE);
  101.       Vabbrev_start_location = Qnil;
  102.       if (BUF_FETCH_CHAR (buf, wordstart) == '-')
  103.     buffer_delete_range (buf, wordstart, wordstart + 1, 0);
  104.     }
  105.   else
  106.     wordstart = scan_words (buf, BUF_PT (buf), -1);
  107.  
  108.   if (!wordstart)
  109.     return value;
  110.  
  111.   wordend = scan_words (buf, wordstart, 1);
  112.   if (!wordend)
  113.     return value;
  114.  
  115.   if (wordend > BUF_PT (buf))
  116.     wordend = BUF_PT (buf);
  117.   whitecnt = BUF_PT (buf) - wordend;
  118.   if (wordend <= wordstart)
  119.     return value;
  120.  
  121.   p = buffer = (Bufbyte *) alloca (MAX_EMCHAR_LEN*(wordend - wordstart));
  122.  
  123.   for (idx = wordstart; idx < wordend; idx++)
  124.     {
  125.       REGISTER Emchar c = BUF_FETCH_CHAR (buf, idx);
  126.       if (UPPERCASEP (buf, c))
  127.     c = DOWNCASE (buf, c), uccount++;
  128.       else if (! NOCASEP (buf, c))
  129.     lccount++;
  130.       p += emchar_to_charptr (c, p);
  131.     }
  132.  
  133.   if (VECTORP (buf->abbrev_table))
  134.     sym = oblookup (buf->abbrev_table,
  135.             buffer,
  136.             p - buffer);
  137.   else
  138.     sym = Qzero;
  139.   if (INTP (sym) || NILP (XSYMBOL (sym)->value))
  140.     sym = oblookup (Vglobal_abbrev_table,
  141.             buffer,
  142.             p - buffer);
  143.   if (INTP (sym) || NILP (XSYMBOL (sym)->value))
  144.     return value;
  145.  
  146.   if (INTERACTIVE && !EQ (minibuf_window, Fselected_window (Qnil)))
  147.     {
  148.       BUF_SET_PT (buf, wordend);
  149.       Fundo_boundary ();
  150.     }
  151.   BUF_SET_PT (buf, wordstart);
  152.   Vlast_abbrev_text =
  153.     make_string_from_buffer (buf, wordstart, wordend - wordstart);
  154.   buffer_delete_range (buf, wordstart, wordend, 0);
  155.  
  156.   /* Now sym is the abbrev symbol. */
  157.   Vlast_abbrev = sym;
  158.   last_abbrev_point = wordstart;
  159.  
  160.   if (INTP (XSYMBOL (sym)->plist))
  161.     XSETINT (XSYMBOL (sym)->plist,
  162.          XINT (XSYMBOL (sym)->plist) + 1);    /* Increment use count */
  163.  
  164.   expansion = XSYMBOL (sym)->value;
  165.   buffer_insert_lisp_string (buf, expansion);
  166.   BUF_SET_PT (buf, BUF_PT (buf) + whitecnt);
  167.  
  168.   if (uccount && !lccount)
  169.     {
  170.       /* Abbrev was all caps */
  171.       /* If expansion is multiple words, normally capitalize each word */
  172.       /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
  173.      but Megatest 68000 compiler can't handle that */
  174.       if (!abbrev_all_caps)
  175.     if (scan_words (buf, BUF_PT (buf), -1) >
  176.         scan_words (buf, wordstart, 1))
  177.       {
  178.         upcase_initials_region (buf, make_number (wordstart),
  179.                     make_number (BUF_PT (buf)));
  180.         goto caped;
  181.       }
  182.       /* If expansion is one word, or if user says so, upcase it all. */
  183.       Fupcase_region (make_number (wordstart), make_number (BUF_PT (buf)),
  184.               lbuf);
  185.     caped: ;
  186.     }
  187.   else if (uccount)
  188.     {
  189.       /* Abbrev included some caps.  Cap first initial of expansion */
  190.       int speccount = specpdl_depth ();
  191.       Bufpos old_pt = BUF_PT (buf);
  192.  
  193.       /* Don't let Fcapitalize_word operate on text after point.  */
  194.       record_unwind_protect (save_restriction_restore,
  195.                  save_restriction_save ());
  196.       Fnarrow_to_region (make_number (BUF_BEGV (buf)),
  197.              make_number (BUF_PT (buf)), lbuf);
  198.  
  199.       BUF_SET_PT (buf, wordstart);
  200.       Fcapitalize_word (make_number (1), lbuf);
  201.       BUF_SET_PT (buf, old_pt);
  202.  
  203.       unbind_to (speccount, Qnil);
  204.     }
  205.  
  206.   hook = XSYMBOL (sym)->function;
  207.   if (!NILP (hook) && !EQ (hook, Qunbound))
  208.     call0 (hook);
  209.  
  210.   return Qt;
  211. }
  212.  
  213. void
  214. syms_of_abbrev (void)
  215. {
  216.   defsymbol (&Qpre_abbrev_expand_hook, "pre-abbrev-expand-hook");
  217.   defsubr (&Sexpand_abbrev);
  218. }
  219.  
  220. void
  221. vars_of_abbrev (void)
  222. {
  223.   DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
  224.     "The abbrev table whose abbrevs affect all buffers.\n\
  225. Each buffer may also have a local abbrev table.\n\
  226. If it does, the local table overrides the global one\n\
  227. for any particular abbrev defined in both.");
  228.   Vglobal_abbrev_table = Qnil;  /* setup by Lisp code */
  229.  
  230.   DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
  231.     "The abbrev-symbol of the last abbrev expanded.\n\
  232. See the function `abbrev-symbol'.");
  233.  
  234.   DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
  235.     "The exact text of the last abbrev expanded.\n\
  236. nil if the abbrev has already been unexpanded.");
  237.  
  238.   DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
  239.     "The location of the start of the last abbrev expanded.");
  240.  
  241.   Vlast_abbrev = Qnil;
  242.   Vlast_abbrev_text = Qnil;
  243.   last_abbrev_point = 0;
  244.  
  245.   DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
  246.     "Buffer position for `expand-abbrev' to use as the start of the abbrev.\n\
  247. nil means use the word before point as the abbrev.\n\
  248. Calling `expand-abbrev' sets this to nil.");
  249.   Vabbrev_start_location = Qnil;
  250.  
  251.   DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
  252.     "Buffer that `abbrev-start-location' has been set for.\n\
  253. Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
  254.   Vabbrev_start_location_buffer = Qnil;
  255.  
  256.   DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
  257.     "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
  258.   abbrev_all_caps = 0;
  259.  
  260.   DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
  261.     "Function or functions to be called before abbrev expansion is done.\n\
  262. This is the first thing that `expand-abbrev' does, and so this may change\n\
  263. the current abbrev table before abbrev lookup happens.");
  264.   Vpre_abbrev_expand_hook = Qnil;
  265. }
  266.